﻿using ImGuiNET;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.GraphicsLibraryFramework;
using TrinityEngine.SceneManagement;
using TrinityEngine.Test;

namespace TrinityEngine
{
    public class Engine : GameWindow
    {
        private ImGuiController _controller;

        private PhysicsWorld _world;

        private float _timeCounter;

        private SpriteBatcher _spriteBatcher;

        public Engine() : base(
            GameWindowSettings.Default,
            new NativeWindowSettings()
            {
                Size = new Vector2i(Screen.width, Screen.height),
                Title = PlayerSettings.productName
            })
        { }

        protected override void OnLoad()
        {
            base.OnLoad();

            _controller = new ImGuiController(ClientSize.X, ClientSize.Y);

            _world = new PhysicsWorld();

            _spriteBatcher = new SpriteBatcher(1024);

            SceneManager.LoadScene(0);
        }

        protected override void OnUpdateFrame(FrameEventArgs args)
        {
            base.OnUpdateFrame(args);

            Time.Update();

            if (_timeCounter >= Time.fixedDeltaTime)
            {
                _world.Update();
                SceneManager.GetActiveScene().FixedUpdate();
                _timeCounter = 0f;
            }
            else
            {
                _timeCounter += Time.deltaTime;
            }

            SceneManager.GetActiveScene().Update();

            Input.LateUpdate();

            if (KeyboardState.IsKeyDown(Keys.Escape))
            {
                Close();
            }
        }

        protected override void OnRenderFrame(FrameEventArgs args)
        {
            base.OnRenderFrame(args);

            _controller.Update(this, (float)args.Time);

            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            _spriteBatcher.Render();

            SceneManager.GetActiveScene().Render();

            SceneManager.GetActiveScene().RenderUI();

            SceneManager.ShowDebugMenu();

            _controller.Render();

            SwapBuffers();
        }

        protected override void OnResize(ResizeEventArgs e)
        {
            base.OnResize(e);

            GL.Viewport(0, 0, e.Width, e.Height);

            _controller.WindowResized(ClientSize.X, ClientSize.Y);

            Screen.OnResize(e.Width, e.Height);
        }

        protected override void OnUnload()
        {
            base.OnUnload();
            SceneManager.OnUnload();
            _controller.Dispose();
            _spriteBatcher.Dispose();
        }

        protected override void OnTextInput(TextInputEventArgs e)
        {
            base.OnTextInput(e);

            _controller.PressChar((char)e.Unicode);
        }

        protected override void OnMouseWheel(MouseWheelEventArgs e)
        {
            base.OnMouseWheel(e);

            _controller.MouseScroll(e.Offset);
        }
    }
}
